#pragma once
#include <stdint.h>
#include <mutex>
#include <fstream>
struct AVFrame;

/// @brief 休眠ms 毫秒
/// @param ms 
void MSleep(uint64_t ms);
long long NowMs();
///////////////////////////////////////////
///// 视屏渲染接口类
///// 1.隐藏SDL实现
///// 2.渲染方案可替代
///// 3.线程安全
class XVideoView
{
public:
    enum Format // 和ffmpeg一致
    {
        YUV420P = 0, // YU12
        ARGB = 25,
        RGBA = 26,
        BGRA = 28,
    };
    enum RenderType
    {
        SDL = 0,
        // QT,
        // XV,
    };
    virtual ~XVideoView() = default;
    static XVideoView *Create(RenderType type);
    /// 初始化渲染窗口
    /// @param w,h 视频分辨率
    /// @param fmt 视频格式
    /// @return 成功返回true
    virtual bool Init(int w, int h,
                      Format fmt = RGBA) = 0;
    /// 渲染图像 线程安全（主要是考虑和Init的互斥）
    /// @param data 图像数据
    /// @param linesize 图像数据行字节数，对于yuv420p，为y一行的字节数
    /// 如果linesize<=0，那么根据视频格式计算（对齐方式无法确定）
    /// @return 成功返回true
    virtual bool Draw(const uint8_t *data, int linesize = 0) = 0;
    /// @brief
    /// @param y
    /// @param y_pitch
    /// @param u
    /// @param u_pitch
    /// @param v
    /// @param v_pitch
    /// @return
    virtual bool Draw(const uint8_t *y, int y_pitch,
                      const uint8_t *u, int u_pitch,
                      const uint8_t *v, int v_pitch) = 0;
    /// @brief 绘制一帧视频，默认实现是根据frame的格式来调用上面的不同的draw函数
    /// @param frame 需要播放的AVFrame帧
    /// @return 成功方式true，否则放回false
    virtual bool DrawFrame(AVFrame *frame);
    // 显示缩放
    void Scale(int w, int h)
    {
        scale_w_ = w;
        scale_h_ = h;
    }

    // 清理所有的资源包括关闭窗口
    virtual void Close() = 0;

    // 处理窗口退出事件
    virtual bool IsExit() = 0;
    int render_fps() const { return render_fps_; }
    // 打开文件 线程不安全
    bool Open(std::string filepath);
    /// @brief 设置窗口句柄，需要在Init前调用
    /// @param win_id 窗口句柄
    void set_win_id(void *win_id) { win_id_ = win_id; }

    /// @brief 读取一帧数据，并维护AVFrame空间，每次调用会覆盖上一次数据且线程不安全
    /// @return
    AVFrame *Read();

protected:
    void *win_id_ = nullptr;
    int render_fps_ = 0;
    int width_ = 0;     // 纹理宽高
    int height_ = 0;    // 纹理宽高
    Format fmt_ = RGBA; // 像素格式
    std::mutex mutex_;  // 互斥锁
    // 渲染宽高,不设置的话就全屏显示
    int scale_w_ = 0;
    int scale_h_ = 0;
    long long beg_ms_ = 0;
    int count_ = 0;

private:
    std::ifstream ifs_;
    AVFrame *frame_ = nullptr;
};